package com.eta.gateway.filter;

import com.eta.common.constant.HeaderConstant;
import com.eta.common.constant.ResultCodeEnum;
import com.eta.common.utils.JwtUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.util.Arrays;
import java.util.List;

/**
 * @author 星河一叶Ck
 * @date 2025/9/8
 * @description 认证过滤器
 */

@Configuration
@Slf4j
@RequiredArgsConstructor
public class AuthGlobalFilter {
    private final JwtUtils jwtUtils;

    // 白名单， 无需登录的接口
    private static final List<String> WHITE_LIST = Arrays.asList(
            "/api/auth/login",
            "/api/auth/register",
            "/api/auth/send-sms-code"
    );

    @Bean
    @Order(-100) // 优先级： 数字越小越先执行（确保认证在路由前完成）
    public GlobalFilter authFilter() {
        return (exchange, chain) -> {
            ServerHttpRequest request = exchange.getRequest();
            String path = request.getURI().getPath();

            // 白名单直接方形
            if (WHITE_LIST.stream().anyMatch(path::startsWith)) {
                return chain.filter(exchange);
            }

            // 读取token
            String token = request.getHeaders().getFirst(HeaderConstant.AUTHORIZATION);

            if (token == null || !token.startsWith(HeaderConstant.BEARER_PREFIX)) {
                return handleAuthError(exchange, ResultCodeEnum.USER_NOT_LOGIN);
            }
            token = token.substring(HeaderConstant.BEARER_PREFIX.length()).trim();

            // 验证token有效性
            if (jwtUtils.isTokenExpired(token)) {
                log.warn("token已过期： {}", token);
                return handleAuthError(exchange, ResultCodeEnum.USER_TOKEN_INVALID);
            }

            String userId = jwtUtils.getUserIdFormToken(token);
            if (userId == null) {
                return handleAuthError(exchange, ResultCodeEnum.USER_TOKEN_INVALID);
            }

            ServerHttpRequest modifiedRequest = request.mutate()
                    .header(HeaderConstant.X_USER_ID, userId)
                    .build();

            return chain.filter(exchange.mutate().request(modifiedRequest).build());
        };
    }

    /**
     * 认证失败响应（返回统一错误格式）
     */
    private Mono<Void> handleAuthError(ServerWebExchange exchange, ResultCodeEnum code) {
        ServerHttpResponse response = exchange.getResponse();
        response.setStatusCode(HttpStatus.UNAUTHORIZED); // 401
        response.getHeaders().add("Content-Type", "application/json;charset=UTF-8");

        // 构建错误响应体
        String errorBody = String.format(
                "{\"code\": %d, \"msg\": \"%s\", \"data\": null}",
                code.getCode(),
                code.getMsg()
        );
        return response.writeWith(Mono.just(response.bufferFactory().wrap(errorBody.getBytes())));
    }


}
